package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.MyThreadLocal;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @DubboReference
    private MovementApi movementApi;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    //发布动态
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {

        //判断
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }

        Long userId = MyThreadLocal.getUserId();
        ArrayList<String> list = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            list.add(upload);
        }
        movement.setUserId(userId);
        movement.setMedias(list);

        movementApi.publish(movement);

    }

    //我的动态
    public PageResult findByUserId(Long userid, Integer page, Integer pagesize) {
        //根据用户id，调用API查询个人动态内容（PageResult  -- Movement）
        PageResult pr = movementApi.findByUserId(userid, page, pagesize);

        List<Movement> items = (List<Movement>) pr.getItems();
        if (items == null) {
            return pr;
        }

        UserInfo userInfo = userInfoApi.getById(userid);
        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        pr.setItems(vos);
        return pr;
    }

    //好友动态
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        Long userId = MyThreadLocal.getUserId();

        //查询到好友动态
        List<Movement> list = movementApi.findFriendMovements(userId, page, pagesize);

        return getPageResult(page, pagesize, list);

    }

    /**
     * 根据动态列表分页查询到PageResult
     *
     * @param page
     * @param pagesize
     * @param list
     * @return
     */
    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> list) {
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //获取到list中所有的userId
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //根据用户的id列表获取用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);

        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = map.get(movement.getUserId());
            if (movement != null) {
                MovementsVo vo = MovementsVo.init(userInfo, movement);

                String key =Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY+MyThreadLocal.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }

                String key1 =Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
                String hashKey1 = Constants.MOVEMENT_LOVE_HASHKEY+MyThreadLocal.getUserId();
                if (redisTemplate.opsForHash().hasKey(key1,hashKey1)){
                    vo.setHasLiked(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page, pagesize, 0, vos);
    }

    //推荐动态
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        String redisKey = Constants.MOVEMENTS_RECOMMEND + MyThreadLocal.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);

        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            //随机推荐一页动态
            list = movementApi.randomMovements(pagesize);
        } else {
            String[] split = redisValue.split(",");

            //判断当前页的起始条数是否大于数字总条数
            if ((page - 1) * pagesize < split.length) {
                List<Long> pids = Arrays.stream(split).skip((page - 1) * pagesize).limit(pagesize)
                        .map(x -> Long.valueOf(x))
                        .collect(Collectors.toList());

                list = movementApi.findMovementsByPids(pids);
            }
        }
        return getPageResult(page, pagesize, list);
    }

    //根据id查询动态详情
    public MovementsVo findById(String movementId) {
        Movement movement =movementApi.findById(movementId);
        if(movement != null) {
            UserInfo userInfo = userInfoApi.getById(movement.getUserId());
            return MovementsVo.init(userInfo,movement);
        }else {
            return null;
        }
    }
    //点赞
    public Integer likeComment(String movementId) {

        Boolean hasLike =movementApi.hasLike(movementId,MyThreadLocal.getUserId(),CommentType.LIKE);
        if (hasLike){
            throw new BusinessException(ErrorResult.likeError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(MyThreadLocal.getUserId());
        comment.setCreated(System.currentTimeMillis());
        //调用API保存数据到Mongodb
        Integer count = movementApi.save(comment);

        //拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + MyThreadLocal.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;

    }

    //取消点赞
    public Integer disLikeComment(String movementId) {
        Boolean hasLike =movementApi.hasLike(movementId,MyThreadLocal.getUserId(),CommentType.LIKE);
        if (!hasLike){
            throw new BusinessException(ErrorResult.disLikeError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(MyThreadLocal.getUserId());
        //调用API保存数据到Mongodb
        Integer count = movementApi.delete(comment);

        //拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + MyThreadLocal.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }

    //喜欢
    public Integer loveComment(String movementId) {
        Boolean hasLike =movementApi.hasLike(movementId,MyThreadLocal.getUserId(),CommentType.LOVE);
        if (hasLike){
            throw new BusinessException(ErrorResult.loveError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(MyThreadLocal.getUserId());
        comment.setCreated(System.currentTimeMillis());
        //调用API保存数据到Mongodb
        Integer count = movementApi.save(comment);

        //拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + MyThreadLocal.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;
    }

    //取消喜欢
    public Integer unLoveComment(String movementId) {
        Boolean hasLike =movementApi.hasLike(movementId,MyThreadLocal.getUserId(), CommentType.LOVE);
        if (!hasLike){
            throw new BusinessException(ErrorResult.disLoveError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(MyThreadLocal.getUserId());
        //调用API保存数据到Mongodb
        Integer count = movementApi.delete(comment);

        //拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + MyThreadLocal.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }


    //首页-访客列表
    public List<VisitorsVo> queryVisitorsList() {
        //1、查询访问时间
        String key = Constants.VISITORS_USER;
        String hashKey = String.valueOf(MyThreadLocal.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null:Long.valueOf(value);
        //2、调用API查询数据列表 List<Visitors>
        List<Visitors> list =  visitorsApi.queryMyVisitors(date,MyThreadLocal.getUserId());
        if(CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        //3、提取用户的id
        List<Long> userIds = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        //4、查看用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        //5、构造返回
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if(userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, visitors);
                vos.add(vo);
            }
        }
        return vos;
    }
}
